<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/26 0026
 * Time: 15:45
 */
namespace s_time_task;

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'TimerBase.php'; // 该文件必须引入，该文件是框架的初始化

/**
 * 多进程测试
 *
 * Class ProcessTest
 * @package s_time_task
 */
class ProcessTest {
    public $mpid = 0;
    public $works = [];
    public $max_precess = 4;
    public $new_index = 0;

    public function __construct()
    {
        try {
            \swoole_set_process_name(sprintf('php-ps:%s', 'master'));
            $this->mpid = posix_getpid();
            $this->run();
            $this->processWait();
            echo 'ok' . PHP_EOL;
        }catch (\Exception $e){
            die('ALL ERROR: '.$e->getMessage());
        }
    }

    public function run()
    {
        for ($i = 0; $i < $this->max_precess; $i++) {
            $this->new_index = $i;
            $this->CreateProcess();
        }
    }

    public function CreateProcess($index = null)
    {
        if(is_null($index)) {
            $index = $this->new_index;
        }

        $process = new \swoole_process(function(\swoole_process $worker) use ($index) {
            \swoole_set_process_name(sprintf('php-ps:%s', $index));

            for ($j = 0; $j < 5; $j++) {
                $this->checkMpid($worker);
                // echo "msg: {$j}\n";
                sleep(1);
            }

        }, false, false);

        $pid = $process->start();
        $this->works[$index] = $pid;

        return $pid;
    }

    public function checkMpid(&$worker)
    {
        if(!\swoole\process::kill($this->mpid, 0)){
            $worker->exit();
            // 这句提示,实际是看不到的.需要写到日志中
            echo "Master process exited, I [{$worker['pid']}] also quit\n";
        }
    }

    public function rebootProcess($ret)
    {
        $pid = $ret['pid'];
        $index = array_search($pid, $this->works);
        if(false !== $index){
            $index = intval($index);
            $new_pid = $this->CreateProcess($index);
            echo "rebootProcess: {$index} = {$new_pid} Done" . PHP_EOL;
            return;
        }
        throw new \Exception('rebootProcess Error: no pid' . PHP_EOL);
    }

    public function processWait()
    {
        while(1) {
            if(count($this->works)){
                $ret = \swoole\process::wait();
                if ($ret) {
                    $this->rebootProcess($ret);
                }
            }else{
                break;
            }
        }
    }
}

new ProcessTest();